﻿/* ***** BEGIN LICENSE BLOCK *****
 *
 * The contents of this file are subject to the Mozilla Public License Version 1.1
 * (the "License"); you may not use this file except in compliance with the
 * License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
 * the specific language governing rights and limitations under the License.
 * 
 * The Original Code is CnCNet Client code, Released 2nd January 2009.
 * 
 * The Initial Developers of the Original Code are
 * Adam Krock and John Sanderson. Portions created by
 * the Initial Developer are Copyright (C) 2010
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s): Adam Krock, John Sanderson.
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either of the GNU General Public License Version 2 or later (the "GPL"),
 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 * 
 * ***** END LICENSE BLOCK *****/

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Management;
using System.Net;
using System.IO;
using System.IO.Compression;

namespace CnCNet
{
    public static class methods
    {
        public static int getHashCode(byte[] b)
        {
            int tempOne = b[12] + b[13] + b[14] + b[15];
            tempOne = tempOne + b[16] + b[17] + b[18] + b[19];
            tempOne = tempOne + (b[20] + b[21]) * (b[22] + b[23]);
            return tempOne;
        }

        public static byte[] RawSerializeEx(object o)
        {
            int rawsize = Marshal.SizeOf(o);
            byte[] rawdatas = new byte[rawsize];
            GCHandle handle = GCHandle.Alloc(rawdatas, GCHandleType.Pinned);
            IntPtr buffer = handle.AddrOfPinnedObject();
            Marshal.StructureToPtr(o, buffer, false);
            handle.Free();
            return rawdatas;
        }

        public static byte[] RawSerialize(object o)
        {
            int rawsize = Marshal.SizeOf(o);
            IntPtr buffer = Marshal.AllocHGlobal(rawsize);
            Marshal.StructureToPtr(o, buffer, false);
            byte[] rawdatas = new byte[rawsize];
            Marshal.Copy(buffer, rawdatas, 0, rawsize);
            Marshal.FreeHGlobal(buffer);
            return rawdatas;
        }

        public static ushort[] getUshortArray(byte[] b)
        {
            int tempOne = b.Length / 2;
            if (b.Length % 2 != 0)
            {
                tempOne = b.Length + 2;
            }
            ushort[] tempTwo = new ushort[tempOne];
            Buffer.BlockCopy(b, 0, tempTwo, 0, b.Length);
            return tempTwo;
        }

        public static int IPAddressToInt(string a)
        {
            return BitConverter.ToInt32(System.Net.IPAddress.Parse(a).GetAddressBytes(), 0);
        }

        public static IPAddress getInternalIp()
        {
            ManagementClass mgmt = new ManagementClass("Win32_NetworkAdapterConfiguration");
            ManagementObjectCollection objCol = mgmt.GetInstances();
            IPAddress ip = IPAddress.None, temp;
            String[] ips;

            foreach (ManagementObject obj in objCol)
            {
                if ((bool)obj["IPEnabled"] == true)
                {
                    ips = (string[])obj["IPAddress"];
                    if (ips[0].StartsWith("5"))
                    {
                        temp = IPAddress.Parse(ips[1]);
                    }
                    else
                    {
                        temp = IPAddress.Parse(ips[0]);
                    }

                    if ((obj["DefaultIPGateway"] != null)
                        && (temp.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
                        && (!IPAddress.IsLoopback(temp)))
                    {
                        return temp;
                    }
                }
                obj.Dispose();
            }
            return ip;
        }
        
        #region Packet related methods


        // 10

        public static ushort htnus(ushort us)
        {
            byte[] tempOne = BitConverter.GetBytes(us);
            Array.Reverse(tempOne);
            return BitConverter.ToUInt16(tempOne, 0);
        }

        public static uint htnui(uint ui)
        {
            byte[] tempOne = BitConverter.GetBytes(ui);
            Array.Reverse(tempOne);
            return BitConverter.ToUInt32(tempOne, 0);
        }

        public static byte[] getChatMessage(int dst, short port, string sender, string message)
        {
            cncNetcodec.packets.encode.chat tempOne = new cncNetcodec.packets.encode.chat(dst, port, sender, message);
            return methods.RawSerialize(tempOne);
        }

        public static ushort udpChecksum(ushort udpLength, byte[] src, byte[] dst, byte[] buffer)
        {
            ushort protocol = 17;
            ushort padding = 0;
            ushort word16;
            uint sum;

            if (udpLength % 2 != 0)
            {
                padding = 1;
                buffer[udpLength] = 0;
            }

            sum = 0;

            for (int i = 0; i < udpLength + padding; i = i+2)
            {
                word16 = (ushort)(((buffer[i] << 8) & 0xFF00) + (buffer[i+1] & 0xFF));
                sum = sum + (uint)word16;
            }

            for (int i = 0; i < 4; i = i + 2)
            {
                word16 = (ushort)(((src[i] << 8) & 0xFF00) + (src[i + 1] & 0xFF));
                sum = sum + (uint)word16;
            }

            for (int i = 0; i < 4; i = i + 2)
            {
                word16 = (ushort)(((dst[i] << 8) & 0xFF00) + (dst[i + 1] & 0xFF));
                sum = sum + (uint)word16;
            }

            sum = sum + (uint)protocol + (uint)+udpLength;

            while ((sum>>16) != 0)
            {
                sum = (sum & 0xFFFF) + (sum >> 16);
            }

            sum = ~sum;

            return ((ushort)sum);
        }

        public static bool isCnCPacket(byte[] b)
        {
            if (b[29].Equals(52) && b[30].Equals(18))
            {
                return true;
            }
            return false;
        }

        public static bool isBroadcast(byte[] b)
        {
            if (isCnCPacket(b))
            {
                if (b[31].Equals(1) && b[49].Equals(0))
                {
                    return true;
                }
            }
            return false;
        }

        #endregion
    }
}
